`timescale	1ps/1ps
module L9_com_ctrl_02(
		input	wire		resetb,
		input	wire		sclk,
		input	wire		comm_en,

		//设备参数
		input	wire		sub_mode,
		input	wire	[9:0]	current_depth,
		input	wire	[5:0]	device_port,

		input	wire		rec_flag,
		input	wire		rec_error,
		input	wire	[7:0]	rec_data,
		
		input	wire		blank_flag,
		input	wire		redu_flag,
		input	wire		time_1ms_sync,
		
		input	wire		op_addr_mask,

		output	wire		spi2_cs,
		output	wire		spi2_clk,
		output	wire		spi2_mosi,

		//universe读接口	
		output	reg	[4:0]	universe_r_addr,
		input	wire	[15:0]	universe_r_data,
		
		
		//显示数据输出
		output	wire		artnet_flag,
		output	reg		dsout,
		output	reg	[7:0]	dout,
		output	reg		h_start,
		output	reg	[10:0]	h_num,
		output	wire		l2048_mode,
		
		output	wire	[7:0]	tout
		);

//************************************************/
//		参数定义
//************************************************/
parameter  IDLE_STATE		= 3'b001;
parameter  COM_RECEIVE		= 3'b010;
parameter  ARTNET_PROC		= 3'b100;

parameter  SPI2_DIV		= 6;

//**********************************************/
//		信号定义
/***********************************************/
reg	[2:0]	com_state;
wire		receive_flag;

reg	[7:0]	rec_d, rec_t;
wire	[15:0]	rec_16d, rec_16dl;

reg	[8:0]	rec_count;
reg		mac_flag, arp_flag, ipv4_flag, udp_flag, l9_port_flag, art_port_flag;
reg		v8_flag, l9_flag, iColor_flag;
reg		iColor_cmd_flag, icolor_mcu;
reg	[5:0]	iColor_h_count;
reg		art_flag, art_mcu, art_dmxdata_flag, artnet_command;
reg		artnet_proc_end;

reg	[5:0]	art_proc_count;

reg		rec_flag_t;
reg		config_flag, config_wen;
reg	[3:0]	config_count;
reg	[7:0]	config_data;
 
reg		rec_buf_wen;
reg	[9:0]	rec_buf_waddr;
wire	[12:0]	rec_buf_raddr;
reg	[7:0]	rec_buf_wdata;
wire		rec_buf_rdata;

reg		universe_load, universe_load_t, d_length_load;
reg	[14:0]	universe_c;
reg	[9:0]	o_max, o_count, w_count;
reg	[4:0]	port_max, cmp_count;
reg		read_flag, cmp_flag, match_flag, out_flag;
reg	[3:0]	read_flag_t, out_flag_t;
wire	[7:0]	buf_rdata;
reg		buf_wen;

//*************************************************/
//		通讯buf
//*************************************************/	
L9_swsr_1kw8_8kr1_dp	rec_buf(
	.wrclock(sclk),
	.wren(rec_buf_wen),
	.wraddress(rec_buf_waddr),
	.data(rec_buf_wdata),
	
	.rdclock(sclk),
	.rdaddress(rec_buf_raddr),
	.q(rec_buf_rdata)
	);

//************************************************/
//		通讯包发送到MCU接口
//************************************************/
reg	[8:0]	rec_buf_count, send_spi_length;
reg	[18:0]	send_spi_count;
reg		rec_end, send_spi_start, rec_buf_w_sel, send_spi_flag, send_spi_last;
reg		send_spi_req, send_spi_en;

//***************接收控制***************
//接收写缓冲使能
always@(posedge sclk)
	rec_flag_t <= rec_flag;
		
//接收计数
always@(posedge sclk)
	if ((rec_flag == 0) && (rec_flag_t == 0))
		rec_buf_count <= 8;		//保留8个字节的包头
	else if ((rec_flag == 1) && (rec_buf_count[8:6] != 3'b111))
		rec_buf_count <= rec_buf_count + 1;
		
//接收结束标志
always@( * )
	 if ((rec_flag == 0 && rec_flag_t == 1))
		rec_end <= 1;
	else
		rec_end <= 0;
		
//***************转发控制***************
//上一包未转发完成，不能发送新包
always @( * )
	send_spi_en = ~send_spi_flag;

//转发使能
always@(posedge sclk)
	if ((art_mcu == 1) || (arp_flag == 1) || (icolor_mcu == 1))
		send_spi_req <= 1;
	else
		send_spi_req <= 0;

//SPI转发开始
always@(posedge sclk)
	if ((comm_en == 1) && (rec_end == 1) && (send_spi_req == 1) && (send_spi_en == 1))
		send_spi_start <= 1;
	else
		send_spi_start <= 0;

//切换地址区
always@(posedge sclk or negedge resetb)
	if (resetb == 0)
		rec_buf_w_sel <= 0;
	else if (send_spi_start == 1)
		rec_buf_w_sel <= ~rec_buf_w_sel;

//保存转发长度
always@(posedge sclk or negedge resetb)
	if (resetb == 0)
		send_spi_length <= 0;
	else if (send_spi_start == 1)
		send_spi_length <= rec_buf_count;

//SPI转发使能
always@(posedge sclk or negedge resetb)
	if (resetb == 0)
		send_spi_flag <= 0;
	else if (send_spi_start == 1)
		send_spi_flag <= 1;
	else if (send_spi_last == 1)
		send_spi_flag <= 0;

//SPI转发计数
always@(posedge sclk)
	if (send_spi_flag == 0)
		send_spi_count <= 0;
	else
		send_spi_count <= send_spi_count + 1;

//SPI转发结束
always@(posedge sclk)
	if ((send_spi_flag == 1) && (send_spi_count[SPI2_DIV + 12:SPI2_DIV + 4] == send_spi_length))
		send_spi_last <= 1;
	else
		send_spi_last <= 0;

//***************反馈包头中附加配置数据***************
//配置使能
always@(posedge sclk or negedge resetb)
	if (resetb == 0)
		config_flag <= 0;
	else if (send_spi_start == 1)
		config_flag <= 1;
	else if (config_count[3] == 1)
		config_flag <= 0;

//配置计数
always@(posedge sclk)
	if (config_flag == 0)
		config_count <= 0;
	else
		config_count <= config_count + 1;

//配置使能：第三个字节
always@(posedge sclk)
	if (config_flag == 0)
		config_wen <= 0;
	else if (config_count == (3 - 2))
		config_wen <= 1;
	else if (config_count == (4 - 2))
		config_wen <= 1;
	else
		config_wen <= 0;

//配置数据：当前级联深度
always@(posedge sclk)
	if (config_flag == 0)
		config_data <= 0;
	else if (config_count == (3 - 2))
		config_data <= current_depth[7:0];
	else if (config_count == (4 - 2))
		config_data <= {sub_mode, 5'h00, current_depth[9:8]};
	else
		config_data <= 0;

//***************缓冲控制***************
always@(posedge sclk)
	if ((rec_flag == 1) || (config_wen == 1))
		rec_buf_wen <= 1;
	else
		rec_buf_wen <= 0;

always@(posedge sclk)
	if (rec_flag == 1)
		rec_buf_wdata <= rec_data;
	else if (config_wen == 1)
		rec_buf_wdata <= config_data;
	else
		rec_buf_wdata <= 0;
	
always@(posedge sclk)
	if (rec_flag == 1)
		rec_buf_waddr <= {rec_buf_w_sel, rec_buf_count[8:0]};
	else if (config_wen == 1)
		rec_buf_waddr <= {~rec_buf_w_sel, 5'h0, config_count[3:0]};
	else
		rec_buf_waddr <= 0;

assign	rec_buf_raddr = {~rec_buf_w_sel, send_spi_count[SPI2_DIV + 12:SPI2_DIV + 1]};

//***************输出给MCU的信号***************
assign	spi2_cs = ~send_spi_flag;
assign	spi2_clk = send_spi_count[SPI2_DIV];
assign	spi2_mosi = rec_buf_rdata;

//************************************************/
//		状态控制
//************************************************/
//**************主状态机*******************
always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		com_state <= IDLE_STATE;
	else 
		case(com_state)
			IDLE_STATE:	
				if (comm_en == 1 && rec_flag == 1)
					com_state <= COM_RECEIVE;	

			COM_RECEIVE:
				if (rec_flag == 0) begin
					if (rec_error == 1)
						com_state <= IDLE_STATE;
					else if (artnet_command == 1)
						com_state <= ARTNET_PROC;
					else
						com_state <= IDLE_STATE;
					end
					
			ARTNET_PROC:
				if(artnet_proc_end == 1)
					com_state <= IDLE_STATE;
							
			default:	com_state <= IDLE_STATE;
		endcase

//***************ARTNET_PROC处理*******************
always	@(posedge sclk)
	if(com_state != ARTNET_PROC)
		art_proc_count <= 0;
	else
		art_proc_count <= art_proc_count + 1;

always	@(posedge sclk)
	if (art_dmxdata_flag == 1)
		artnet_proc_end <= art_proc_count[5];
	else
		artnet_proc_end <= 1;

//**************通讯包接收类型判断*******************
//接收标志
assign	receive_flag = com_state[1];

always	@(posedge sclk) begin
	rec_d <= rec_data;
	rec_t <= rec_d;
	end

assign	rec_16d = {rec_t,rec_d};
assign	rec_16dl = {rec_d,rec_t};

//数据计数
always	@(posedge sclk)
	if (receive_flag == 0)
		rec_count <= 0;
	else if (rec_count[8] == 0)
		rec_count <= rec_count + 1;

//V8包类型判断
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		mac_flag <= 0;
	else if (rec_count == (22 - 9) && rec_16d == 16'h55AA)
		mac_flag <= 1;

//ipv4包类型判断
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		ipv4_flag <= 0;
	else if (rec_count == (22 - 9) && rec_16d == 16'h0800)
		ipv4_flag <= 1;

//ipv4包类型判断
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		arp_flag <= 0;
	else if (rec_count == (22 - 9) && rec_16d == 16'h0806)
		arp_flag <= 1;

//UDP包类型判断
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		udp_flag <= 0;
	else if (ipv4_flag == 1 && rec_count == (32 - 9) && rec_d == 8'h11)
		udp_flag <= 1;

//L9端口判断
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		l9_port_flag <= 0;
	else if (udp_flag == 1 && rec_count == (46 - 9) && rec_16d == 16'h55AA)
		l9_port_flag <= 1;

//ArtNet端口判断
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		art_port_flag <= 0;
	else if (udp_flag == 1 && rec_count == (46 - 9) && rec_16d == 16'h1936)
		art_port_flag <= 1;

//V8包标志
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		v8_flag <= 0;
	else if (mac_flag == 1 && rec_count == (23 - 9) && rec_d == 8'h81)
		v8_flag <= 1;
			
//L9包标志
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		l9_flag <= 0;
	else if (l9_port_flag == 1 && rec_count == (51 - 9) && rec_d == 8'h81)
		l9_flag <= 1;
			
//智彩协议标志
always	@( * )
	if (v8_flag == 1 || l9_flag == 1)
		iColor_flag <= 1;
	else
		iColor_flag <= 0;

//智彩包头计数
always	@(posedge sclk)
	if (iColor_flag == 0)
		iColor_h_count <= 0;
	else if (iColor_h_count[5] == 0)
		iColor_h_count <= iColor_h_count + 1;

//智彩命令标志
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		iColor_cmd_flag <= 0;
	else if ((iColor_flag == 1) && (iColor_h_count == (52 - 51 - 1)) && (rec_d == 8'hC5))
		iColor_cmd_flag <= 1;

//ArtNet包标志
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		art_flag <= 0;
	else if (art_port_flag == 1 && rec_count == (51 - 9) && rec_d == "A")
		art_flag <= 1;
		
////Madix包标志
//always	@(posedge sclk)
//	if (com_state == IDLE_STATE)
//		madix_flag <= 0;
//	else if (art_port_flag == 1 && rec_count == (51 - 9) && rec_d == "M")
//		madix_flag <= 1;
		
//iColor 通讯命令包提取
always	@(posedge sclk)
	if (com_state == IDLE_STATE)
		icolor_mcu <= 0;
	else if (iColor_cmd_flag == 1 && op_addr_mask == 1)
		icolor_mcu <= 1;
	else
		icolor_mcu <= 0;

//ArtNet包类型提取
always	@(posedge sclk)
	if (com_state == IDLE_STATE) begin
		art_dmxdata_flag <= 0;
		art_mcu <= 0;
		end
	else if (art_flag == 1 && rec_count == (60 - 9))
		case(rec_16dl)
			16'h2000:	art_mcu <= 1;
			16'h8000:	art_mcu <= 1;
			16'h8200:	art_mcu <= 1;
			16'h8300:	art_mcu <= 1;
			16'h5000:	art_dmxdata_flag <= 1;
		endcase		

//处理ART_NET标志
always	@(posedge sclk)
	artnet_command = art_dmxdata_flag;

assign	artnet_flag = art_dmxdata_flag;
	
//**********************************************************************/
//		信息提取
//**********************************************************************/
//行号提取标志
always	@(posedge sclk)
	if (art_dmxdata_flag == 1 && rec_count == (65 - 9))
		universe_load <= 1;
	else
		universe_load <= 0;

//行号提取
always	@(posedge sclk)
	if (universe_load == 1)
		universe_c <= rec_16dl;

//行长提取标志
always	@(posedge sclk) begin
	universe_load_t <= universe_load;
	d_length_load <= universe_load_t;
	end

//行长提取
always	@(posedge sclk)
	if (d_length_load == 1)
		o_max <= rec_16d - 1;

//**********************************************************************/
//		universe比较
//**********************************************************************/
//最大端口号
always	@(posedge sclk)
	if (device_port[5] == 1)
		port_max <= 5'h1F;
	else 
		port_max = device_port - 1;
	
//使能读universe号
always	@(posedge sclk)
	if (universe_load == 1)
		read_flag <= 1;
	else if (universe_r_addr == port_max)
		read_flag <= 0;

//读universe号地址
always	@(posedge sclk)
	if (read_flag == 0)
		universe_r_addr <= 0;
	else
		universe_r_addr <= universe_r_addr + 1;

//等待数据返回
always	@(posedge sclk)
	read_flag_t <= {read_flag_t[3:0], read_flag};

//比较使能
always	@(posedge sclk)
	if (read_flag_t[2:1] == 2'b01)
		cmp_flag <= 1;
	else if (read_flag_t[1] == 1'b0)
		cmp_flag <= 0;
	else if (match_flag == 1)
		cmp_flag <= 0;

//比较计数
always	@(posedge sclk)
	if (cmp_flag == 0)
		cmp_count <= 0;
	else
		cmp_count <= cmp_count + 1;

//匹配标志
always	@(posedge sclk)
	if ((cmp_flag == 0) || (match_flag == 1))
		match_flag <= 0;
	else if (universe_r_data == universe_c)
		match_flag <= 1;
	else
		match_flag <= 0;
		
//**********************************************************************/
//		数据输出
//**********************************************************************/
//匹配端口号
always	@(posedge sclk)
	if (match_flag == 1)
		h_num <= cmp_count - 1;

//输出标志
always	@(posedge sclk)
	if (match_flag == 1)
		out_flag <= 1;
	else if (o_count == o_max)
		out_flag <= 0;
	
//输出标志
always	@(posedge sclk)
	if (out_flag == 1)
		o_count <= 0;
	else
		o_count <= o_count + 1;
	
//延时处理
always	@(posedge sclk)
	out_flag_t <= {out_flag_t[2:0], out_flag};

//输出信号
always	@(posedge sclk)
	if (out_flag_t[3:1] == 2'b10)
		h_start <= 1;
	else
		h_start <= 0;
		
always	@( * )
	dsout <= out_flag_t[3];

always	@(posedge sclk)
	dout <= buf_rdata;

assign	l2048_mode = 0;
		
/************************************************/
//		DMX包缓存输出
/************************************************/
phy_sram_1024_8_sdp artdmx_buf(
	.wrclock(sclk),
	.wren(buf_wen),
	.wraddress(w_count),
	.data(rec_d),
	.rdclock(sclk),
	.rdaddress(o_count),
	.q(buf_rdata)
	);

always	@(posedge sclk)
	if (d_length_load == 1)
		buf_wen <= 1;
	else if (receive_flag == 0)
		buf_wen <= 0;

always	@(posedge sclk)
	if (buf_wen == 0)
		w_count <= 0;
	else
		w_count <= w_count + 1;

/************************************************/
//		测试信号
/************************************************/
assign	tout = {arp_flag, comm_en, ipv4_flag, l9_flag, art_dmxdata_flag, send_spi_req, send_spi_en};

endmodule		
